package com.sh.data.engine.web.webapi.controller.dataquality;

import com.sh.data.engine.application.model.dto.dataquality.DataQualityTableInfoResponse;
import com.sh.data.engine.application.model.dto.normalization.research.ThemeResponse;
import com.sh.data.engine.application.model.request.dataquality.DataQualityAddParExpressionRequest;
import com.sh.data.engine.application.model.request.dataquality.DataQualityRuleRequest;
import com.sh.data.engine.application.model.request.dataquality.SaveDataQualityScheduleRequest;
import com.sh.data.engine.application.service.dataquality.DataQualityManagerApplicationService;
import com.sh.data.engine.domain.annotation.LogExecution;
import com.sh.data.engine.domain.annotation.userlog.Business;
import com.sh.data.engine.domain.annotation.userlog.EngineOperation;
import com.sh.data.engine.domain.base.model.PageResult;
import com.sh.data.engine.domain.dataquality.model.domain.*;
import com.sh.data.engine.web.webapi.controller.base.response.RestResponseEntity;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.List;

/**
 * @author tinglan.ys
 * @description: 数据质量-规则管理相关API
 * @date 2022/2/15 下午6:04
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/dataQuality/manager")
@Tag(name = "数据质量-规则管理", description = "数据质量-规则管理相关API")
public class DataQualityManagerController {

    @Autowired
    private DataQualityManagerApplicationService dataQualityManagerApplicationService;

    /**
     * @description : 查询某个空间下,某个主题下的表信息 新方法
     * @author : tinglan.ys
     * @date : 2022/2/25
     */
//    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @GetMapping("/getTables")
    @Operation(summary = "查询某个空间下,某个主题下的表信息")
    public RestResponseEntity<PageResult<DataQualityTableInfoResponse>> getTables(
        @Parameter(description = "表名") @RequestParam(required = false) String tableName,
        @Parameter(description = "排序方式", schema = @Schema(allowableValues = {"desc", "asc"}))
        @RequestParam(required = false) String order,
        @Parameter(description = "主题Id") @RequestParam(required = false) Long themeId,
        @RequestParam(required = false, defaultValue = "1") Integer pageNum,
        @RequestParam(required = false, defaultValue = "10") Integer pageSize) {
        var result = dataQualityManagerApplicationService.getTables(tableName, order, themeId, pageNum, pageSize);
        return RestResponseEntity.success(result);
    }

    /**
     * @description : 获取模型层级目录结构-列表结构
     * @author : tinglan.ys
     * @date : 2022/2/16
     */
//    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @GetMapping("/getModelDirList")
    @Operation(summary = "获取模型层级目录结构-列表结构")
    public RestResponseEntity<List<ThemeResponse>> getModelDirList() {
        var result = dataQualityManagerApplicationService.getModelDirList();
        return RestResponseEntity.success(result);
    }

    /**
     * @description : 添加or编辑分区表达式
     * @author : tinglan.ys
     * @date : 2022/2/18
     */
//    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 1, isAdd = 1)
    @PostMapping("/addParExpression")
    @Operation(summary = "添加or编辑分区表达式")
    @LogExecution(operation = EngineOperation.ADD_UPDATE, business = Business.数据质量分区表达式)
//    @Log(
//        business = Business.数据质量分区表达式,
//        operation = Operation.ADD_UPDATE)
    public RestResponseEntity<Boolean> addParExpression(
        @Parameter(description = "参数") @Valid @RequestBody DataQualityAddParExpressionRequest request) {
        var result = dataQualityManagerApplicationService.addParExpression(request);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @GetMapping("/getParExpressions")
    @Operation(summary = "获取分区表达式列表")
    public RestResponseEntity<List<DataQualityTablePartitionDomain>> getParExpressions(
        @Parameter(description = "表id", required = true) @RequestParam Long tblId,
        @Parameter(description = "表名", required = true) @RequestParam String tableName,
        @Parameter(description = "是否有分区", required = true, schema = @Schema(allowableValues = {"0", "1"})) @RequestParam
        Integer hasPartition,
        @Parameter(description = "分区表达式") @RequestParam(required = false) String parExpression) {
        var result = dataQualityManagerApplicationService.getParExpressions(
            tblId, tableName, hasPartition, parExpression);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 1, isAdd = 1)
    @PostMapping("/deleteParExpression")
    @Operation(summary = "删除表达式")
    @LogExecution(operation = EngineOperation.DEL, business = Business.数据质量分区表达式)
//    @Log(
//        business = Business.数据质量分区表达式,
//        operation = Operation.DEL)
    public RestResponseEntity<Boolean> deleteParExpression(
        @Parameter(description = "主键id", required = true) @RequestParam Long id) {
        var result = dataQualityManagerApplicationService.deleteParExpression(id);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 1, isAdd = 1)
    @PostMapping("/saveRule")
    @Operation(summary = "保存规则")
    @LogExecution(operation = EngineOperation.ADD_UPDATE, business = Business.数据质量规则)
//    @Log(
//        business = Business.数据质量规则,
//        operation = Operation.ADD_UPDATE)
    public RestResponseEntity<Boolean> saveRule(
        @Valid @RequestBody DataQualityRuleRequest dataQualityRule) {
        var result = dataQualityManagerApplicationService.saveRule(dataQualityRule);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 1, isAdd = 1)
    @PostMapping("/deleteRule")
    @LogExecution(operation = EngineOperation.DEL, business = Business.数据质量规则)
//    @Log(
//        business = Business.数据质量规则,
//        operation = Operation.DEL)
    @Operation(summary = "删除规则")
    public RestResponseEntity<Boolean> deleteRule(
        @Parameter(description = "规则id", required = true) @RequestParam Long id) {
        var result = dataQualityManagerApplicationService.deleteRule(id);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @GetMapping("/rules")
    @Operation(summary = "获取规则列表，支持模版规则和自定义规则")
    public RestResponseEntity<PageResult<DataQualityRuleDomain>> rules(
        @Parameter(description = "表id", required = true) @RequestParam Long tblId,
        @Parameter(description = "是否为自定义规则 0-否 1-是", schema = @Schema(allowableValues = {"0", "1"}), required = true) @RequestParam
        Integer ruleDiy,
        @Parameter(description = "分区表达式id") @RequestParam(required = false) Long parExpressionId,
        @Parameter(description = "当前页", schema = @Schema(defaultValue = "1"))
        @RequestParam(required = false, defaultValue = "1")
        Integer pageNum,
        @Parameter(description = "每页大小", schema = @Schema(defaultValue = "10"))
        @RequestParam(required = false, defaultValue = "10")
        Integer pageSize) {
        var result = dataQualityManagerApplicationService.getRules(tblId, ruleDiy, parExpressionId, pageNum, pageSize);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @GetMapping("/getRule")
    @Operation(summary = "获取规则详情")
    public RestResponseEntity<DataQualityRuleDetailDomain> getRule(
        @Parameter(description = "规则id", required = true) @RequestParam Object id) {
        var result = dataQualityManagerApplicationService.getRule(id);
        return RestResponseEntity.success(result);
    }

    //  @PostMapping("/saveRuleTemplates")
    //  @Operation(summary = "添加模版规则 后台写死数据，前端不要调用")
    //  public RestResponseEntity<Boolean> saveRuleTemplates() {
    //    return new RestResponseEntity<>(dataQualityManagerService.saveRuleTemplates());
    //  }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @GetMapping("/getRuleTemplates")
    @Operation(summary = "获取模版规则")
    public RestResponseEntity<List<DataQualityRuleTemplateDomain>> getRuleTemplates(
        @Parameter(description = "规则类型,0-单表 1-多表", schema = @Schema(allowableValues = {"0", "1"}), required = true)
        @RequestParam Integer templateTableType) {
        var result = dataQualityManagerApplicationService.getRuleTemplates(templateTableType);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @GetMapping("/getTableFields")
    @Operation(summary = "获取表字段信息")
    public RestResponseEntity<List<DataQualityTableFieldDomain>> getTableFields(
        @Parameter(description = "表id", required = true) @RequestParam Long tblId) {
        var result = dataQualityManagerApplicationService.getTableFields(tblId);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 0, isAdd = 1)
    @Operation(summary = "获取任务调度配置")
    @GetMapping(value = "/schedule/get")
    public RestResponseEntity<DataQualityScheduleDomain> getOfflineTaskSchedule(
        @Parameter(description = "表id", required = true) @RequestParam("tblId") Long tblId) {
        var result = dataQualityManagerApplicationService.getOfflineTaskSchedule(tblId);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 1, isAdd = 1)
    @Operation(summary = "保存任务调度配置", description = "保存任务调度配置")
    @PostMapping(value = "/schedule/save")
    @LogExecution(operation = EngineOperation.ADD_UPDATE, business = Business.数据质量调度配置)
//    @Log(
//        business = Business.数据质量调度配置,
//        operation = Operation.ADD_UPDATE)
    public RestResponseEntity<Boolean> saveOfflineTaskSchedule(
        @Valid @RequestBody SaveDataQualityScheduleRequest request) {
        var result = dataQualityManagerApplicationService.saveOfflineTaskSchedule(request);
        return RestResponseEntity.success(result);
    }

    //    @AuthorityAnnotation(menuId = MenuEnumNew.JKGZ, readWriteStatus = 1, isAdd = 1)
    @Operation(summary = "试跑", description = "试跑")
    @PostMapping(value = "/tryrun")
    @LogExecution(operation = EngineOperation.START_TASK, business = Business.数据质量规则)
//    @Log(
//        business = Business.数据质量规则,
//        operation = Operation.START_TASK)
    public RestResponseEntity<Boolean> tryRun(
        @Parameter(description = "表id", required = true) @RequestParam("tblId") Long tblId,
        @Parameter(description = "分区id") @RequestParam("partitionId") Long partitionId,
        @Parameter(description = "规则ids，不传表示跑这个表下的所有规则，多个id逗号隔开") @RequestParam("ruleIds") String rids) {
        var result = dataQualityManagerApplicationService.tryRun(tblId, partitionId, rids);
        return RestResponseEntity.success(result);
    }
}
